package com.qf.utils;

import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;

/**
 * Jdbc方式---加入Druid连接池,----自动的封装配置文件的所有数据
 * 封装一个静态方法--->获取Connection(从连接池获取)
 * 获取DataSource:数据源----> 连接参数(数据库的信息)以及初始化数量,最大激活数量,最大等待时间
 * 释放资源
 */
public class DruidJdbcUtils {

    //静态实例--->java.lang.ThreadLocal<T>  模拟线程,每一个用户都有自己的Connection
    private static ThreadLocal<Connection> tl = new ThreadLocal<>() ; //里面没有连接对象
    //声明一个DataSource接口类型 变量
    private static DataSource ds ;

    //构造方法私有化
    private DruidJdbcUtils(){}

    //静态代码块
    static{
        try {
            //1)读取德鲁伊的配置文件,让德鲁伊自己封装配置文件参数
            InputStream inputStream = DruidJdbcUtils.class.getClassLoader().getResourceAsStream("druid.properties");
            //创建属性集合列表
            Properties prop = new Properties() ;
            //加载属性集合列表
            prop.load(inputStream) ;
            //2)创建DruidDataSource(连接池)
            ds =  DruidDataSourceFactory.createDataSource(prop);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //获取DataSource数据源信息 (连接池的所有参数)
    public static DataSource getDataSource(){
        return  ds ;
    }

    //从数据源(连接池) 获取连接对象
    public static Connection getConnection(){
        //1)线程本地线程中获取连接对象---ThreadLocal<T>--->T get():从当前线程中获取存储的内容
        Connection conn = tl.get() ;
        try {

            //2)判断
            //如果当前conn对象为null,说明当前线程中没有要操作的连接对象
            if(conn==null){
                //3)从数据源(连接池中)获取Connection
                conn = ds.getConnection();
                //4)将从数据源中获取到的conn连接对象,绑定当当前线程中
                //ThreadLocal<T>--->public void set(T t):绑定
                tl.set(conn) ;
            }

        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        return conn ;
    }

    //释放资源
    public static void  close(ResultSet rs, PreparedStatement stmt, Connection conn){
        if(rs!=null){
            try {
                rs.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        if(stmt!=null){
            try {
                stmt.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        if(conn!=null) {
            try {
                conn.close();
                //从当前线程解绑
                tl.remove();  //ThreadLocal<T> :从线程中移出
            } catch (SQLException throwables) {
                throwables.printStackTrace();

            }
        }
    }


    //主要针对DDL/DML语句操作释放资源
   /* public static void close(Statement stmt,Connection conn){
        close(null,stmt,conn);
    }*/
    public static void close(PreparedStatement stmt,Connection conn){
        close(null,stmt,conn);
    }

    /**
     * 开启事务
     *
     */
    public static void setAutoCommit() throws SQLException {
        //获取连接对象
        Connection conn = getConnection();
        //设置手动提交
        conn.setAutoCommit(false) ;
    }

    /**
     * 事务回滚
     */
    public static void rollbackAndClose() throws SQLException {
        //获取连接对象
        Connection conn = getConnection();
        conn.rollback() ;
        //释放连接对象,从当前线程中解绑
        conn.close() ;
        tl.remove() ;
    }

    /**
     * 提交事务
     */
    public static void commitAndClose() throws SQLException {
        //获取连接对象
        Connection conn = getConnection();
        conn.commit(); ;
        //释放连接对象,从当前线程中解绑
        conn.close();
        tl.remove() ;
    }


    public static void main(String[] args) {


        System.out.println(DruidJdbcUtils.getDataSource());
        System.out.println(DruidJdbcUtils.getConnection());
    }
}
